package com.kakarote.examine.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.TypeUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.kakarote.core.common.Const;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.enums.ExamineLabelEnum;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.SimpleDept;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.feign.crm.entity.CrmBackLogBO;
import com.kakarote.core.feign.crm.entity.ExamineField;
import com.kakarote.core.feign.examine.entity.*;
import com.kakarote.core.feign.oa.OaService;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.*;
import com.kakarote.examine.constant.*;
import com.kakarote.examine.entity.BO.ExamineBO;
import com.kakarote.examine.entity.BO.ExamineFlowBO;
import com.kakarote.examine.entity.BO.ExaminePageBO;
import com.kakarote.examine.entity.BO.ExaminePreviewBO;
import com.kakarote.examine.entity.PO.ExamineRecordLog;
import com.kakarote.examine.entity.PO.*;
import com.kakarote.examine.entity.VO.ExamineRecordInfoVO;
import com.kakarote.examine.entity.VO.ExamineVO;
import com.kakarote.examine.mapper.ExamineMapper;
import com.kakarote.examine.mapper.ExamineRecordLogMapper;
import com.kakarote.examine.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 审批表 服务实现类
 * </p>
 * @author zhangzhiwei
 * @updator qun.xu
 * @since 2020-11-13
 */
@Service
public class ExamineServiceImpl extends BaseServiceImpl<ExamineMapper, Examine> implements IExamineService {

    @Resource IExamineFlowService examineFlowService;
    @Resource IExamineConditionDataService examineConditionDataService;
    @Resource IExamineManagerUserService examineManagerUserService;
    @Resource IExamineConditionService examineConditionService;
    @Resource IExamineRecordOptionalService examineRecordOptionalService;
    @Resource IExamineRecordService examineRecordService;
    @Resource IExamineAdvancedConfigService examineAdvancedConfigService;
    @Resource IExamineRecordLogService examineRecordLogService;
    @Resource IExamineFlowFinalService examineFlowFinalService;
    @Resource IExamineFlowFinalOptionalService examineFlowFinalOptionalService;
    @Resource IExamineFlowMemberComponentService examineFlowMemberComponentService;
    @Resource AdminService adminService;
    @Resource OaService oaService;
    @Resource IExamineFlowAuthFieldService examineFlowAuthFieldService;
    @Resource IExamineAdvancedConfigLimitTimeService advancedConfigLimitTimeService;
    @Resource IExamineAdvancedConfigLimitTimeUsersService advancedConfigLimitTimeUsersService;
    @Resource IExamineFlowOptionalService examineFlowOptionalService;

    private static final int TWO = 2;

    private static final int THREE = 3;

    /**
     * 查询可供设置的自定义字段列表
     *
     * @param label      字段类型
     * @param categoryId 审批分类，只有OA审批需要
     * @return data
     */
    @Override
    public List<ExamineField> queryField(Integer label, Long categoryId) {
        ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(label).getServerName());
        return moduleService.queryExamineField(label, categoryId);
    }

    /**
     * 查询审批列表
     *
     * @param examinePageBo 分页对象
     * @return data
     */
    @Override
    public BasePage<ExamineVO> queryList(ExaminePageBO examinePageBo) {
        UserInfo user = UserUtil.getUser();
        // 获取同层级部门编号
        List<Long> sameLevelDeptId = getSameLevelDeptId(user.getDeptId());
        Long orgId = getDeptOrgIdByDeptId(UserUtil.getUser().getDeptId());
        if (ObjectUtil.isNotEmpty(orgId)){
            sameLevelDeptId.add(orgId);
        }
        BasePage<Examine> basePage = baseMapper.listExaminePage(examinePageBo.parse(), UserUtil.isAdmin(),user.getUserId(), StrUtil.join(Const.SEPARATOR, sameLevelDeptId), examinePageBo.getLabelList());
        BasePage<ExamineVO> page = new BasePage<>(basePage.getCurrent(), basePage.getSize(), basePage.getTotal());
        List<ExamineVO> examineVoList = new ArrayList<>();
        for (Examine examine : basePage.getList()) {
            ExamineVO examineVO = new ExamineVO();
            BeanUtil.copyProperties(examine, examineVO);
            if (!examinePageBo.getIsPart()) {
                examineVO.setCreateUserName(UserCacheUtil.getUserName(examine.getCreateUserId()));
                examineVO.setUpdateUserName(UserCacheUtil.getUserName(examine.getUpdateUserId()));
                examineVO.setManagerList(examineManagerUserService.queryExamineUserByPage(examineVO.getExamineId()));
                //办公审批流可见范围
                if (StrUtil.isNotEmpty(examine.getUserIds())) {
                    Set<Long> userIds = SeparatorUtil.toLongSet(examine.getUserIds());
                    if (CollUtil.isNotEmpty(userIds)) {
                        List<SimpleUser> listResult = UserCacheUtil.getSimpleUsers(userIds);
                        examineVO.setUserList(listResult);
                    } else {
                        examineVO.setUserList(new ArrayList<>());
                    }
                }
                if (StrUtil.isNotEmpty(examine.getDeptIds())) {
                    Set<Long> deptIds = SeparatorUtil.toLongSet(examine.getDeptIds());
                    if (CollUtil.isNotEmpty(deptIds)) {
                        List<SimpleDept> listResult = UserCacheUtil.getDeptList(deptIds);
                        examineVO.setDeptList(listResult);
                    } else {
                        examineVO.setDeptList(new ArrayList<>());
                    }
                }
            }
            //添加语言包key
            Map<String, String> keyMap = new HashMap<>();
            String fieldName = examineVO.getExamineName();
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Id")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Id")).concat("Name");
            }
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Ids")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Ids")).concat("Names");
            }
            keyMap.put("examineName_resourceKey", "defaultParams." + "crmExamine" + examine.getLabel() + "." + fieldName);
            examineVO.setLanguageKeyMap(keyMap);

            ExamineAdvancedConfigVO examineAdvancedConfigVO = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
            examineVO.setAdvancedConfigVO(examineAdvancedConfigVO);
            examineVoList.add(examineVO);
        }
        page.setList(examineVoList);
        return page;
    }

    @Override
    public List<ExamineVO> queryAllList(ExaminePageBO examinePageBo) {
        UserInfo user = UserUtil.getUser();
        List<Examine> allList = this.getBaseMapper().selectAllExamineList(examinePageBo.getSearch(), examinePageBo.getLabel(), UserUtil.isAdmin(), examinePageBo.getIsPart(), user.getUserId(), user.getDeptId(), examinePageBo.getLabelList());
        List<ExamineVO> examineVoList = new ArrayList<>();
        for (Examine examine : allList) {
            ExamineVO examineVO = new ExamineVO();
            BeanUtil.copyProperties(examine, examineVO);
            if (ObjectUtil.isNotEmpty(examine.getExamineIcon())) {
                String[] icons = examine.getExamineIcon().split(",");
                if (icons.length >= 1) {
                    examineVO.setIconClass(icons[0]);
                }
                if (icons.length >= 2) {
                    examineVO.setIconColor(icons[1]);
                }
            }
            if (!examinePageBo.getIsPart()) {
                examineVO.setCreateUserName(UserCacheUtil.getUserName(examine.getCreateUserId()));
                examineVO.setUpdateUserName(UserCacheUtil.getUserName(examine.getUpdateUserId()));
                examineVO.setManagerList(examineManagerUserService.queryExamineUserByPage(examineVO.getExamineId()));
                //办公审批流可见范围
                if (StrUtil.isNotEmpty(examine.getUserIds())) {
                    Set<Long> userIds = SeparatorUtil.toLongSet(examine.getUserIds());
                    if (CollUtil.isNotEmpty(userIds)) {
                        List<SimpleUser> listResult = UserCacheUtil.getSimpleUsers(userIds);
                        examineVO.setUserList(listResult);
                    } else {
                        examineVO.setUserList(new ArrayList<>());
                    }
                }
                if (StrUtil.isNotEmpty(examine.getDeptIds())) {
                    Set<Long> deptIds = SeparatorUtil.toLongSet(examine.getDeptIds());
                    if (CollUtil.isNotEmpty(deptIds)) {
                        List<SimpleDept> listResult = UserCacheUtil.getDeptList(deptIds);
                        examineVO.setDeptList(listResult);
                    } else {
                        examineVO.setDeptList(new ArrayList<>());
                    }
                }
            }
            //添加语言包key
            Map<String, String> keyMap = new HashMap<>();
            String fieldName = examineVO.getExamineName();
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Id")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Id")).concat("Name");
            }
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Ids")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Ids")).concat("Names");
            }
            keyMap.put("examineName_resourceKey", "defaultParams." + "crmExamine" + examine.getLabel() + "." + fieldName);
            examineVO.setLanguageKeyMap(keyMap);

            ExamineAdvancedConfigVO examineAdvancedConfigVO = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
            examineVO.setAdvancedConfigVO(examineAdvancedConfigVO);
            examineVoList.add(examineVO);
        }
        return examineVoList;
    }

    @Override
    public ExamineAdvancedConfigVO queryAdvanceConfig(Long examineId) {
        Examine examineInfo = getById(examineId);
        if (ObjectUtil.isEmpty(examineInfo)) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_EMPTY_ERROR);
        }
        return examineAdvancedConfigService.queryAdvancedConfig(examineInfo.getBatchId());
    }

    /**
     * 保存审批对象，审批对象不可修改，修改是新增一个再把原来的停用
     * @param examineSaveBO data
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Examine addExamine(ExamineSaveBO examineSaveBO) {
        String batchId = IdUtil.simpleUUID();
        /*
          保存审批对象
         */
        Examine examine = saveExamine(examineSaveBO, batchId);
        /*
         * 保存审批流高级配置
         */
        examineAdvancedConfigService.addExamineAdvanceConfig(examine.getExamineId(), examine.getBatchId(), examineSaveBO.getAdvancedConfigBO());
        Long examineId = examine.getExamineId();
        /*
          保存审批管理员对象
         */
        List<Long> longList = examineSaveBO.getManagerList();
        if (CollectionUtil.isNotEmpty(longList)) {
            List<ExamineManagerUser> managerUserList = new ArrayList<>();
            for (int i = 0; i < longList.size(); i++) {
                ExamineManagerUser managerUser = new ExamineManagerUser();
                managerUser.setExamineId(examineId);
                managerUser.setSort(i + 1);
                managerUser.setUserId(longList.get(i));
                managerUserList.add(managerUser);
            }
            examineManagerUserService.saveBatch(managerUserList, Const.BATCH_SAVE_SIZE);
        }
        /*
          保存审批流程数据
         */
        saveExamineFlow(examineSaveBO.getDataList(), examineId, batchId);
        return examine;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Examine addCustomizationExamine(ExamineSaveBO examineSaveBO, Examine oldExamine) {
        String batchId = IdUtil.simpleUUID();
        Examine examine = ObjectUtil.cloneByStream(oldExamine);
        examine.setBatchId(batchId);
        examine.setStatus(3);
        examine.setExamineId(BaseUtil.getNextId());
        examine.setExamineInitId(oldExamine.getExamineId());
        save(examine);

        ExamineAdvancedConfig advancedConfig = examineAdvancedConfigService.lambdaQuery().eq(ExamineAdvancedConfig::getExamineId, examineSaveBO.getExamineId()).one();
        Long oldConfigId = advancedConfig.getAdvancedConfigId();

        advancedConfig.setAdvancedConfigId(BaseUtil.getNextId());
        advancedConfig.setExamineId(examine.getExamineId());
        advancedConfig.setBatchId(batchId);
        examineAdvancedConfigService.save(advancedConfig);


        ExamineAdvancedConfigLimitTime configLimitTime = advancedConfigLimitTimeService.lambdaQuery().eq(ExamineAdvancedConfigLimitTime::getAdvancedConfigId, oldConfigId).one();

        if (ObjectUtil.isNotEmpty(configLimitTime)) {
            Long oldTimeHandleId = configLimitTime.getLimitTimeHandleId();

            configLimitTime.setBatchId(batchId);
            configLimitTime.setAdvancedConfigId(advancedConfig.getAdvancedConfigId());
            configLimitTime.setLimitTimeHandleId(BaseUtil.getNextId());
            configLimitTime.setExamineId(examine.getExamineId());
            advancedConfigLimitTimeService.save(configLimitTime);

            List<ExamineAdvancedConfigLimitTimeUsers> limitTimeUsers = advancedConfigLimitTimeUsersService.lambdaQuery().eq(ExamineAdvancedConfigLimitTimeUsers::getLimitTimeId, oldTimeHandleId).list();

            if (CollUtil.isNotEmpty(limitTimeUsers)) {
                limitTimeUsers.forEach(configLimitTimeUsers -> {
                    configLimitTimeUsers.setLimitTimeId(configLimitTime.getLimitTimeHandleId());
                    configLimitTimeUsers.setBatchId(batchId);
                    configLimitTimeUsers.setHandleId(BaseUtil.getNextId());
                });

                advancedConfigLimitTimeUsersService.saveBatch(limitTimeUsers, Const.BATCH_SAVE_SIZE);
            }
        }
        Long examineId = examine.getExamineId();

        List<ExamineManagerUser> list = examineManagerUserService.lambdaQuery().eq(ExamineManagerUser::getExamineId, examineSaveBO.getExamineId()).list();

        list.forEach(examineManagerUser -> {
            examineManagerUser.setExamineId(examineId);
            examineManagerUser.setId(BaseUtil.getNextId());
        });
        examineManagerUserService.saveBatch(list, Const.BATCH_SAVE_SIZE);

        /*
          保存审批流程数据
         */
        saveExamineFlow(examineSaveBO.getDataList(), examineId, batchId);

        return examine;
    }


    /**
     * 注：由于需求原型上转交他人处理时，当前处理人还在当前审批流节点下，而征求他人意见是生成了新的审批节点
     *
     * @param examineFlowFinalBO
     * @param flowFlag           节点标识（1：初始化，2：申请自定义添加，3：待办征求他人意见）
     * @return
     */
    @Transactional
    @Override
    public Long addExamineFlowFinalNode(ExamineFlowFinalBO examineFlowFinalBO, Integer flowFlag) {

        //查询部当前记录全审批流信息
        List<ExamineFlowFinal> examineFlowFinalList = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getRecordId, examineFlowFinalBO.getRecordId()).orderByAsc(ExamineFlowFinal::getSort, ExamineFlowFinal::getCreateTime).list();
        if (ObjectUtil.isEmpty(examineFlowFinalBO.getExamineId()) && CollectionUtil.isNotEmpty(examineFlowFinalList)) {
            examineFlowFinalBO.setExamineId(examineFlowFinalList.get(0).getExamineId());
        }
        int index = 0;
        for (int i = 0; i < examineFlowFinalList.size(); i++) {
            ExamineFlowFinal curExamineFlowFinal = examineFlowFinalList.get(i);
            if (examineFlowFinalBO.getInsertTarget().equals(curExamineFlowFinal.getFlowId())) {//找到插入点
                index = i;
                break;
            }
        }
        ExamineFlowFinal insertNode = new ExamineFlowFinal();
        BeanUtil.copyProperties(examineFlowFinalBO, insertNode);
        insertNode.setInsertFlag(examineFlowFinalBO.getInsertFlag());
        insertNode.setInsertRemark(examineFlowFinalBO.getRemark());
        insertNode.setFlowFlag(flowFlag);
        switch (examineFlowFinalBO.getInsertFlag()) {
            case 1://插入到目标节点之前
                if (index == 0) {
                    insertNode.setSort(index);
                } else {
                    ExamineFlowFinal examineFlowFinal = examineFlowFinalList.get(index - 1);
                    insertNode.setSort(examineFlowFinal.getSort());
                }
                examineFlowFinalList.add(index, insertNode);
                break;
            case 2://插入到目标节点之后
                ExamineFlowFinal flowFinal = examineFlowFinalList.get(index);
                insertNode.setSort(flowFinal.getSort());
                examineFlowFinalList.add(index + 1, insertNode);
                break;
        }
        Long flowId = null;
        for (int i = 0; i < examineFlowFinalList.size(); i++) {
            ExamineFlowFinal examineFlowFinal = examineFlowFinalList.get(i);
            if (ObjectUtil.isEmpty(examineFlowFinal.getFlowId())) {
                //如果是新增节点
                Long generalId = BaseUtil.getNextId();
                examineFlowFinal.setFlowId(generalId);
//                examineFlowFinal.setSort(i + 1);
                examineFlowFinal.setType(examineFlowFinalBO.getType());
                examineFlowFinal.setExamineId(examineFlowFinalBO.getExamineId());
                examineFlowFinal.setExamineType(ExamineTypeEnum.OPTIONAL.getType());
                examineFlowFinal.setCreateTime(new Date());

                //当前审批人操作征求他人意见log
                ExamineRecordLog recordLog = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getFlowId, examineFlowFinal.getInsertTarget()).eq(ExamineRecordLog::getRecordId, examineFlowFinal.getRecordId()).eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()).eq(ExamineRecordLog::getExamineUserId, UserUtil.getUserId()).one();
                examineFlowFinal.setRelTargetLogId(recordLog.getLogId());
                //保存新插入的节点
                examineFlowFinalService.save(examineFlowFinal);
                List<ExamineFlowFinalUser> insertUserList = examineFlowFinalBO.getUserList();
                List<ExamineFlowFinalOptional> examineFlowFinalOptionalList = new ArrayList<>();
                int userSort = 1;
                for (ExamineFlowFinalUser insertUser : insertUserList) {
                    ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
                    examineFlowFinalOptional.setUserId(insertUser.getUserId());
                    examineFlowFinalOptional.setRecordId(examineFlowFinalBO.getRecordId());
                    examineFlowFinalOptional.setFlowId(generalId);
                    examineFlowFinalOptional.setEmail(insertUser.getEmail());
                    examineFlowFinalOptional.setCreateUserId(UserUtil.getUserId());
                    examineFlowFinalOptional.setCreateTime(new Date());
                    examineFlowFinalOptional.setType(examineFlowFinalBO.getType());
                    examineFlowFinalOptional.setSort(userSort);
                    examineFlowFinalOptionalList.add(examineFlowFinalOptional);
                    ++userSort;
                }
                //保存插入节点对应的员工
                examineFlowFinalOptionalService.saveBatch(examineFlowFinalOptionalList);
                flowId = generalId;
            }
        }
        return flowId;
    }

    /**
     * 通过label查询可用审批流
     *
     * @param label 类型
     * @return data
     */
    @Override
    public Examine queryExamineByLabel(Integer label) {
        return lambdaQuery().eq(Examine::getLabel, label).eq(Examine::getStatus, ExamineStatusEnum.PASS.getStatus()).one();
    }

    /**
     * 保存审批数据
     *
     * @param examineSaveBO data
     * @return 审批ID
     */
    private Examine saveExamine(ExamineSaveBO examineSaveBO, String batchId) {
        Examine oldExamine = null;
        if (examineSaveBO.getExamineId() != null) {
            //如果是修改审批直接将原来停用
            oldExamine = updateStatus(examineSaveBO.getExamineId(), 3, false);
        }
        String examineName = examineSaveBO.getExamineName();
//        boolean exists = false;
//        if (examineSaveBO.getLabel() == ExamineLabelEnum.OA_办公管理.getCode()) {
//            exists = lambdaQuery().eq(Examine::getExamineName, examineName).eq(Examine::getLabel, 0).ne(Examine::getStatus, 3).exists();
//        } else {
//            exists = lambdaQuery().eq(Examine::getExamineName, examineName).ne(Examine::getLabel, 0).ne(Examine::getStatus, 3).exists();
//        }
//        if (exists) {
//            throw new CrmException(ExamineCodeEnum.EXAMINE_NAME_NO_USER_ERROR);
//        }
        Examine examine = new Examine();
        //修改启用的审批或者创建新的直接置为启用
        examine.setStatus((oldExamine != null && oldExamine.getStatus() == 2) ? 2: 1);
        examine.setExamineName(examineName);
        if (oldExamine != null) {
            examine.setOaType(oldExamine.getOaType());
            examine.setExamineInitId(oldExamine.getExamineInitId());
            examine.setExamineId(null);
        }
        examine.setLabel(examineSaveBO.getLabel());
        //todo 超级审核图标处理
        Map<String, Object> icon = examineSaveBO.getExamineIcon();
        if (ObjectUtil.isNotEmpty(icon)) {
            String examineIcon = icon.get("icon") + "," + icon.get("color");
            examine.setExamineIcon(examineIcon);
        }
        examine.setRecheckType(examineSaveBO.getRecheckType());
        examine.setRemarks(examineSaveBO.getRemarks());
        examine.setCreateTime(LocalDateTimeUtil.now());
        examine.setCreateUserId(UserUtil.getUserId());
        examine.setBatchId(batchId);
        examine.setUpdateUserId(UserUtil.getUserId());
        examine.setUpdateTime(LocalDateTimeUtil.now());
        examine.setGroupId(examineSaveBO.getGroupId());
        examine.setIsNeedChild(examineSaveBO.getIsNeedChild());
        if (examineSaveBO.getUserList() != null) {
            List<Long> list = examineSaveBO.getUserList();
            examine.setUserIds(SeparatorUtil.fromSet(list));
        }
        //部门如果为空
        if (ObjectUtils.isEmpty(examineSaveBO.getDeptList())) {
            //当前用户为集团用户
            if(examineSaveBO.getLabel() != ExamineLabelEnum.OA_办公管理.getCode()){
                Long deptId = UserUtil.getUser().getDeptId();
//                examine.setDeptIds(SeparatorUtil.fromSet(Lists.newArrayList(deptId)));
                // 获取部门机构编号
                Long orgId = getDeptOrgIdByDeptId(deptId);
                examine.setDeptIds(SeparatorUtil.fromSet(Lists.newArrayList(orgId)));
                examine.setIsNeedChild(1);//默认权限级联到下级
            }
        } else{
            List<Long> list = examineSaveBO.getDeptList();
            examine.setDeptIds(SeparatorUtil.fromSet(list));
        }
        save(examine);
        if (examine.getLabel() == 0) {
            if (examineSaveBO.getExamineId() != null) {
                oaService.updateFieldCategoryId(examine.getExamineId(), examineSaveBO.getExamineId());
                oaService.updateExaminePrintTemplateCategoryId(examine.getExamineId(), examineSaveBO.getExamineId());
            } else {
                oaService.saveDefaultField(examine.getExamineId());
            }
        }
        if (oldExamine == null) {
            lambdaUpdate().set(Examine::getExamineInitId, examine.getExamineId()).eq(Examine::getExamineId, examine.getExamineId()).update();
        }
        return examine;
    }

    private Long getDeptOrgIdByDeptId(Long deptId) {
        if (deptId == null) {
            return null;
        }
        List<SimpleDept> deptList = adminService.queryDeptList().getData();
        if (!deptList.isEmpty()) {
            Map<Long, SimpleDept> deptMap = deptList.stream().collect(Collectors.toMap(SimpleDept::getId, Function.identity()));
            return getOrgId(deptMap, deptId);
        }
        return null;
    }

    private Long getOrgId(Map<Long, SimpleDept> deptMap, Long deptId) {
        SimpleDept simpleDept = deptMap.get(deptId);
        if (simpleDept == null) {
            return deptId;
        }
        if(simpleDept.getDeptType() == 1){
            return simpleDept.getId();
        }else{
            return getOrgId(deptMap, simpleDept.getParentId());
        }
    }


    /**
     * 保存审批流程数据
     */
    private void saveExamineFlow(List<ExamineDataSaveBO> dataList, Long examineId, String batchId) {
        int i = 1;
        for (ExamineDataSaveBO nodeBo : dataList) {
            ExamineFlow node = new ExamineFlow();
            node.setExamineType(nodeBo.getExamineType());
            node.setExamineId(examineId);
            node.setName(nodeBo.getName());
            node.setConditionId(0L);
            node.setBindLabel(nodeBo.getBindLabel());
            node.setCreateTime(LocalDateTimeUtil.now());
            node.setCreateUserId(UserUtil.getUserId());
            node.setExamineErrorHandling(nodeBo.getExamineErrorHandling());
            node.setSort(i++);
            node.setBatchId(batchId);
            examineFlowService.save(node);
            //关联流程类型。
            if(nodeBo.getExamineType()==ExamineTypeEnum.BIND_LABEL.getType() &&   node.getBindLabel()!=null){
                continue;
            }
            ExamineTypeEnum examineTypeEnum = ExamineTypeEnum.valueOf(nodeBo.getExamineType());
            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(examineTypeEnum.getServerName());
            examineTypeService.saveExamineFlowData(nodeBo, node.getFlowId(), batchId);
            //处理外层审批节点字段授权，条件节点下在对应的条件节点处理
            List<ExamineFieldAuthBO> fieldAuthList = nodeBo.getFieldAuthList();
            if (fieldAuthList != null) {
                List<ExamineFlowAuthField> flowAuthFields = new ArrayList<>();
                for (ExamineFieldAuthBO examineFieldAuthBO : fieldAuthList) {
                    ExamineFlowAuthField flowAuthField = new ExamineFlowAuthField();
                    flowAuthField.setId(BaseUtil.getNextId());
                    flowAuthField.setFlowId(node.getFlowId());
                    flowAuthField.setAuthLevel(examineFieldAuthBO.getAuthLevel());
                    flowAuthField.setFieldId(examineFieldAuthBO.getFieldId());
                    flowAuthField.setFieldName(examineFieldAuthBO.getFieldName());
                    flowAuthField.setExamineId(examineId);
                    flowAuthField.setCreateTime(new Date());
                    flowAuthField.setCreateUserId(UserUtil.getUserId());
                    flowAuthField.setLabel(examineFieldAuthBO.getLabel());
                    flowAuthField.setTableLevel(examineFieldAuthBO.getTableLevel());
                    if (ObjectUtil.isNotEmpty(examineFieldAuthBO.getFieldExtendList())) {
                        flowAuthField.setHasChildren(1);
                        for (ExamineFieldAuthBO fieldAuthBO : examineFieldAuthBO.getFieldExtendList()) {
                            ExamineFlowAuthField extendField = new ExamineFlowAuthField();
                            extendField.setId(BaseUtil.getNextId());
                            extendField.setFlowId(node.getFlowId());
                            extendField.setAuthLevel(fieldAuthBO.getAuthLevel());
                            extendField.setFieldId(fieldAuthBO.getFieldId());
                            extendField.setFieldName(fieldAuthBO.getFieldName());
                            extendField.setExamineId(examineId);
                            extendField.setCreateTime(new Date());
                            extendField.setCreateUserId(UserUtil.getUserId());
                            extendField.setLabel(fieldAuthBO.getLabel());
                            extendField.setHasChildren(0);
                            extendField.setParentId(flowAuthField.getId());
                            flowAuthFields.add(extendField);
                        }
                    }
                    flowAuthFields.add(flowAuthField);
                }
                examineFlowAuthFieldService.saveBatch(flowAuthFields);
            }
        }
    }

    /**
     * 修改审批状态
     *
     * @param examineId 审批ID
     * @param status    1 正常 2 停用 3 删除
     */
    @Override
    public Examine updateStatus(Long examineId, Integer status, boolean isRequest) {

        if (!ObjectUtil.isAllNotEmpty(examineId, status)) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        if (!Arrays.asList(1, TWO, THREE).contains(status)) {
            return null;
        }
        Examine examine = getById(examineId);
        if (examine == null) {
            return null;
        }
        //默认办公审批禁止删除
        int four = 4;
        int five = 5;
        int six = 6;
        int seven = 7;
        if (isRequest && Objects.equals(THREE, status) && ListUtil.toList(1, TWO, THREE, four, five, six, seven).contains(examine.getOaType())) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_SPECIAL_TYPE_NOT_DELETE_ERROR);
        }
        /*
          状态相同直接跳过
         */
        Integer oldStatus = examine.getStatus();
        if (oldStatus.equals(status)) {
            return examine;
        }

        /*
          已删除审批不允许进行其他操作
         */
        if (Objects.equals(THREE, oldStatus)) {
            return examine;
        }
        /*
          每个类型只允许一个启用的审批
         */
        if (Objects.equals(1, status)) {
            Integer label = examine.getLabel();
            if (label != 0) {
                boolean exists = lambdaQuery().eq(Examine::getLabel, examine.getLabel()).eq(Examine::getStatus, 1).exists();
                if (exists) {
                    throw new CrmException(ExamineCodeEnum.EXAMINE_START_ERROR);
                }
            }
        }
        //只修改审批状态字段
        lambdaUpdate().set(Examine::getStatus, status).eq(Examine::getExamineId, examineId).update();

        return examine;
    }

    @Override
    public List<ExamineFlowVO> queryExamineFlow(Long examineId) {
        Examine examine = this.getById(examineId);
        return getExamineFlowVOList(examine, null);
    }


    @Override
    public List<ExamineFlowConditionDataVO> previewFiledName(Integer label, Long recordId, Long examineId) {
        Examine examine;
        if (examineId == null) {
            if (recordId == null) {
                examine = lambdaQuery().eq(Examine::getLabel, label).eq(Examine::getStatus, 1).one();
            } else {
                //针对历史审批数据查看
                ExamineRecord record = examineRecordService.getById(recordId);
                Long exId = Optional.ofNullable(record).orElse(new ExamineRecord()).getExamineId();
                examine = this.getById(exId);
            }
        } else {
            //OA办公审批专用
            examine = this.getById(examineId);
        }
        if (examine == null) {
            return null;
        }

        List<ExamineFlowConditionDataVO> conditionDataVoS = new ArrayList<>();

        ExamineFlow flow = examineFlowService.lambdaQuery().eq(ExamineFlow::getExamineId, examine.getExamineId()).last("limit 1").one();
        if (flow == null) {
            return new ArrayList<>();
        }
        String batchId = flow.getBatchId();
        QueryWrapper<ExamineFlow> flowQueryWrapper = new QueryWrapper<>();
        flowQueryWrapper.eq("batch_id", batchId);
        flowQueryWrapper.ne("condition_id", 0);
        flowQueryWrapper.select("condition_id");

        List<String> conditionIds = examineFlowService.listObjs(flowQueryWrapper, Object::toString);

        if (ObjectUtil.isNotEmpty(conditionIds)) {
            List<ExamineConditionData> list = examineConditionDataService.lambdaQuery().in(ExamineConditionData::getConditionId, conditionIds).list();
            if (ObjectUtil.isNotEmpty(list)) {
                for (ExamineConditionData examineConditionData : list) {
                    ExamineFlowConditionDataVO examineFlowConditionDataVO = new ExamineFlowConditionDataVO();
                    examineFlowConditionDataVO.setFieldId(examineConditionData.getFieldId());
                    examineFlowConditionDataVO.setName(examineConditionData.getName());
                    examineFlowConditionDataVO.setConditionType(examineConditionData.getConditionType());
                    examineFlowConditionDataVO.setGroupId(examineConditionData.getGroupId());
                    examineFlowConditionDataVO.setValues(examineConditionData.getValue());
                    examineFlowConditionDataVO.setType(examineConditionData.getType());
                    examineFlowConditionDataVO.setFieldName(examineConditionData.getFieldName());
                    conditionDataVoS.add(examineFlowConditionDataVO);
                }
            }
        }
        conditionDataVoS.removeIf(conditionDataVo -> ConditionTypeEnum.PERSONNEL.getType().equals(conditionDataVo.getConditionType()));
        return conditionDataVoS;
    }

    @Override
    public ExaminePreviewVO previewExamineFlow(ExaminePreviewBO examinePreviewBO) {
        ExaminePreviewVO examinePreviewVO = new ExaminePreviewVO();
        Examine examine;
        Long recordId = examinePreviewBO.getRecordId();
        if (examinePreviewBO.getExamineId() == null) {
            if (recordId == null) {
                examine = lambdaQuery().eq(Examine::getLabel, examinePreviewBO.getLabel()).eq(Examine::getStatus, 1).one();
            } else {
                ExamineRecord record = examineRecordService.getById(recordId);
                Long examineId = Optional.ofNullable(record).orElse(new ExamineRecord()).getExamineId();
                examine = this.getById(examineId);
            }
        } else {
            //OA审批
            examine = this.getById(examinePreviewBO.getExamineId());
        }
        if (examine == null) {
            return examinePreviewVO;
        }
        examinePreviewVO.setRemarks(examine.getRemarks());
        //----------------------------------------------------------------
        //获取高级设置
        ExamineAdvancedConfigVO examineAdvancedConfigVO = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
        examineAdvancedConfigVO.setExamineId(examine.getExamineId());
        //添加高级设置
        examinePreviewVO.setExamineAdvancedConfigVO(examineAdvancedConfigVO);
        /**
         * 超级审核处理
         *
         */
        List<ExamineFlowVO> examineFlowVOList;
        if (ObjectUtil.isNotNull(examinePreviewBO.getRecordId())) {
            List<ExamineFlowFinalVO> examineFlowFinalVOList = examineFlowFinalService.queryFinalFlowList(examinePreviewBO.getRecordId());

            if (CollectionUtil.isNotEmpty(examineFlowFinalVOList)) {
                List<ExamineFlowVO> examineFlowVoS = new ArrayList<>();
                examineFlowFinalVOList.forEach(examineFlowFinalVO -> {
                    ExamineFlowVO examineFlowVO = new ExamineFlowVO();
                    List<ExamineFlowFinalUser> finalUserList = examineFlowFinalVO.getUserList();
                    List<SimpleUser> simpleUserList = new ArrayList<>();
                    BeanUtil.copyProperties(examineFlowFinalVO, examineFlowVO, "userList");
                    if (CollectionUtil.isNotEmpty(finalUserList)) {
                        finalUserList.forEach(finalUser -> {
                            SimpleUser simpleUser = new SimpleUser();
                            if (ObjectUtil.isNotEmpty(finalUser.getUserId())) {
                                simpleUser = UserCacheUtil.getSimpleUser(finalUser.getUserId());
                            }
                            if (ObjectUtil.isNotEmpty(finalUser.getEmail())) {
                                simpleUser.setOuterUserEmail(finalUser.getEmail());
                            }
                            simpleUserList.add(simpleUser);
                        });

                    }
                    examineFlowVO.setFinalUserList(simpleUserList);
                    if (CollectionUtil.isEmpty(examineFlowVO.getUserList())) {
                        examineFlowVO.setUserList(simpleUserList);
                    }
                    examineFlowVoS.add(examineFlowVO);
                });
                examinePreviewVO.setExamineFlowList(examineFlowVoS);
            } else {
                examineFlowVOList = getExamineFlowVOList(examine, examinePreviewBO.getOwnerUserId());
                Map<String, Object> dataMap = examinePreviewBO.getDataMap();
                List<ExamineFlowVO> examineFlowVoS = new ArrayList<>();
                this.getAllConformExamineFlow(examineFlowVOList, dataMap, examineFlowVoS);

                //非初始审批 - 新建数据之后预览流程时补充自选用户信息
                this.supplementOptionalUserInfo(examineFlowVoS, examinePreviewBO.getRecordId(), examine.getExamineId());
                examinePreviewVO.setExamineFlowList(examineFlowVoS);
            }
        } else {
            examineFlowVOList = getExamineFlowVOList(examine, examinePreviewBO.getOwnerUserId());
            Map<String, Object> dataMap = examinePreviewBO.getDataMap();
            List<ExamineFlowVO> examineFlowVoS = new ArrayList<>();
            this.getAllConformExamineFlow(examineFlowVOList, dataMap, examineFlowVoS);
            //非初始审批 - 新建数据之后预览流程时补充自选用户信息
            this.supplementOptionalUserInfo(examineFlowVoS, examinePreviewBO.getRecordId(), examine.getExamineId());
            examinePreviewVO.setExamineFlowList(examineFlowVoS);

        }

        //添加语言包key
        Map<String, String> keyMap = new HashMap<>();
        String fieldName = examinePreviewVO.getRemarks();
        if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Id")) {
            fieldName = fieldName.substring(0, fieldName.lastIndexOf("Id")).concat("Name");
        }
        if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Ids")) {
            fieldName = fieldName.substring(0, fieldName.lastIndexOf("Ids")).concat("Names");
        }
        keyMap.put("remarks_resourceKey", "defaultParams." + "crmExamine" + examinePreviewBO.getLabel() + "Remarks" + examinePreviewBO.getLabel() + "." + fieldName);
        examinePreviewVO.setLanguageKeyMap(keyMap);

        ExamineAdvancedConfig examineAdvancedConfig = examineAdvancedConfigService.lambdaQuery().eq(ExamineAdvancedConfig::getExamineId, examine.getExamineId()).one();
        if (ObjectUtil.isNotEmpty(examineAdvancedConfig)) {
            String modify = examineAdvancedConfig.getModifyPermissionType();
            if (StringUtils.isNotEmpty(modify)) {
                List<Integer> modifyPermissionTypeList = Arrays.stream(modify.split(",")).map(Integer::valueOf).collect(Collectors.toList());
                examinePreviewVO.setModifyPermissionType(modifyPermissionTypeList);
            }
        }
        return examinePreviewVO;
    }


    /**
     * 预览审批流程时补充自选用户信息
     *
     * @param examineFlowVoS
     * @param recordId
     * @param examineId
     * @return void
     **/
    private void supplementOptionalUserInfo(List<ExamineFlowVO> examineFlowVoS, Long recordId, Long examineId) {
        for (ExamineFlowVO examineFlowVO : examineFlowVoS) {
            if (ExamineTypeEnum.OPTIONAL.getType().equals(examineFlowVO.getExamineType())) {
                List<ExamineRecordOptional> optionalUsers = examineRecordOptionalService.lambdaQuery().eq(ExamineRecordOptional::getFlowId, examineFlowVO.getFlowId()).eq(ExamineRecordOptional::getRecordId, recordId).orderByAsc(ExamineRecordOptional::getSort).list();
                if (CollUtil.isNotEmpty(optionalUsers)) {
                    List<Long> userIds = optionalUsers.stream().map(ExamineRecordOptional::getUserId).collect(Collectors.toList());
                    List<ExamineFlowFinalUser> userList = new ArrayList<>();
                    userIds.forEach(userId -> {
                        ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                        examineFlowFinalUser.setUserId(userId);
                        userList.add(examineFlowFinalUser);
                    });
                    List<ExamineFlowFinalUser> users = handleUserList(userList, examineId);
                    List<ExamineFlowFinalUser> outerUserList = new ArrayList<>();
                    List<Long> innerUserId = new ArrayList<>();
                    users.forEach(examineFlowFinalUser -> {
                        if (ObjectUtil.isNull(examineFlowFinalUser.getUserId()) && StringUtils.isNotEmpty(examineFlowFinalUser.getEmail())) {
                            outerUserList.add(examineFlowFinalUser);//外部审核人员
                        }
                        if (ObjectUtil.isNotNull(examineFlowFinalUser.getUserId())) {
                            innerUserId.add(examineFlowFinalUser.getUserId());
                        }
                    });
                    List<SimpleUser> simpleUsers = UserCacheUtil.getSimpleUsers(innerUserId);
                    outerUserList.forEach(outerUser -> {
                        SimpleUser simpleUser = new SimpleUser();
                        simpleUser.setOuterUserEmail(outerUser.getEmail());
                    });
                    examineFlowVO.setUserList(simpleUsers);
                    if (ObjectUtil.isEmpty(examineFlowVO.getFinalUserList())) {
                        examineFlowVO.setFinalUserList(simpleUsers);
                    }
                }
            }
        }
    }

    @Override
    public List<ExamineFlowFinalUser> handleUserList(List<ExamineFlowFinalUser> examineFlowFinalUserList, Long examineId) {
        List<ExamineFlowFinalUser> outerUserList = new ArrayList<>();
        List<ExamineFlowFinalUser> innerUserList = new ArrayList<>();
        List<Long> innerUserId = new ArrayList<>();

        examineFlowFinalUserList.forEach(examineFlowFinalUser -> {
            if (ObjectUtil.isNull(examineFlowFinalUser.getUserId()) && StringUtils.isNotEmpty(examineFlowFinalUser.getEmail())) {
                examineFlowFinalUser.setEmail(examineFlowFinalUser.getEmail());
                outerUserList.add(examineFlowFinalUser);
            }
            if (ObjectUtil.isNotNull(examineFlowFinalUser.getUserId())) {
                innerUserList.add(examineFlowFinalUser);
                innerUserId.add(examineFlowFinalUser.getUserId());
            }
        });

        List<ExamineFlowFinalUser> userList = new ArrayList<>();
        if (CollUtil.isNotEmpty(innerUserList)) {
            AdminService adminService = ApplicationContextHolder.getBean(AdminService.class);
            List<Long> userIdList = adminService.queryNormalUserByIds(innerUserId).getData();
            if (CollectionUtil.isNotEmpty(userIdList)) {
                userIdList.forEach(userId -> {
                    ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                    examineFlowFinalUser.setUserId(userId);
                    userList.add(examineFlowFinalUser);
                });
            }
        }
        if (userList.size() == 0 && CollectionUtil.isEmpty(outerUserList)) {
            IExamineManagerUserService examineManagerUserService = ApplicationContextHolder.getBean(IExamineManagerUserService.class);
            List<Long> userIdList = examineManagerUserService.queryExamineUser(examineId);
            if (CollectionUtil.isNotEmpty(userIdList)) {
                userIdList.forEach(userId -> {
                    ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                    examineFlowFinalUser.setUserId(userId);
                    userList.add(examineFlowFinalUser);
                });
            }
        }
        userList.addAll(outerUserList);
        return userList;
    }

    /**
     * 查询审批INFO
     *
     * @param examineId 审批ID
     */
    @Override
    public ExaminePreviewVO queryExamineFlowInfo(Long examineId) {
        Examine examine = getById(examineId);
        ExaminePreviewVO examinePreviewVO = new ExaminePreviewVO();
        List<ExamineFlowVO> flowVOList = getExamineFlowVOList(examine, null);
        examinePreviewVO.setRecheckType(examine.getRecheckType());
        examinePreviewVO.setRemarks(examine.getRemarks());
        examinePreviewVO.setExamineFlowList(flowVOList);
        List<Long> examineUser = examineManagerUserService.queryExamineFlowInfoUser(examineId);

        examinePreviewVO.setManagerList(examineUser);
        //获取高级设置
        ExamineAdvancedConfigVO examineAdvancedConfigVO = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
        examinePreviewVO.setExamineAdvancedConfigVO(examineAdvancedConfigVO);
        return examinePreviewVO;
    }


    /**
     * 获取最终的审批流程
     *
     * @param examineFlowVOList
     * @param dataMap
     * @param examineFlowVoS
     * @return void
     **/
    private void getAllConformExamineFlow(List<ExamineFlowVO> examineFlowVOList, Map<String, Object> dataMap, List<ExamineFlowVO> examineFlowVoS) {
        for (ExamineFlowVO examineFlowVO : examineFlowVOList) {
            List<ExamineFlowConditionVO> conditionList = examineFlowVO.getConditionList();
            if (CollUtil.isNotEmpty(conditionList)) {
                for (ExamineFlowConditionVO examineFlowConditionVO : conditionList) {

                    List<ExamineFlowConditionDataVO> conditionDataList = examineFlowConditionVO.getConditionDataList().stream().flatMap(Collection::stream).collect(Collectors.toList());
                    //有条件执行情况
                    if (CollUtil.isNotEmpty(conditionDataList)) {
                        List<ExamineConditionData> conditions = new ArrayList<>();
                        conditionDataList.forEach(examineFlowConditionDataVO -> {
                            ExamineConditionData examineConditionData = new ExamineConditionData();
                            BeanUtil.copyProperties(examineFlowConditionDataVO, examineConditionData);
                            examineConditionData.setValue(JSON.toJSONString(examineFlowConditionDataVO.getValues()));
                            //此处备份一下json字符串值 留作后面判断使用
                            examineConditionData.setBackupValue(JSON.toJSONString(examineFlowConditionDataVO.getBackupValue()));
                            conditions.add(examineConditionData);
                        });
                        Object createUserId = dataMap.get(ExamineConst.CREATE_USER_ID);
                        UserInfo userInfo;
                        if (createUserId != null) {
                            userInfo = UserCacheUtil.getUserInfo(TypeUtils.castToLong(createUserId));
                        } else {
                            userInfo = UserUtil.getUser();
                        }
                        boolean isPass = examineConditionService.handleExamineConditionData(conditions, dataMap, userInfo);
                        if (isPass) {
                            List<ExamineFlowVO> examineDataList = examineFlowConditionVO.getExamineDataList();
                            if (CollUtil.isNotEmpty(examineDataList)) {
                                this.getAllConformExamineFlow(examineDataList, dataMap, examineFlowVoS);
                            }
                            break;
                        }
                    } else {
                        //如果条件为空则视为无条件
                        List<ExamineFlowVO> examineDataList = examineFlowConditionVO.getExamineDataList();
                        if (CollUtil.isNotEmpty(examineDataList)) {
                            this.getAllConformExamineFlow(examineDataList, dataMap, examineFlowVoS);
                        }
                        break;
                    }
                }
            } else {
                examineFlowVoS.add(examineFlowVO);
            }
        }
    }


    /**
     * 获取所有的节点
     *
     * @param examine
     * @param ownerUserId
     * @return java.util.List<com.kakarote.core.feign.examine.entity.ExamineFlowVO>
     **/
    private List<ExamineFlowVO> getExamineFlowVOList(Examine examine, Long ownerUserId) {
        if (examine == null) {
            return new ArrayList<>();
        }
        String batchId = examine.getBatchId();
        List<ExamineFlow> examineFlowList = examineFlowService.lambdaQuery().eq(ExamineFlow::getBatchId, batchId).list();
        Map<Long, List<ExamineFlow>> listMap = examineFlowList.stream().collect(Collectors.groupingBy(ExamineFlow::getConditionId));
        //获取条件ID为0的数据，即最上级的审批流
        List<ExamineFlow> examineFlows = listMap.remove(0L);
        if (CollUtil.isEmpty(examineFlows)) {
            return new ArrayList<>();
        }
        //排序，升序
        examineFlows.sort((Comparator.comparing(ExamineFlow::getSort)));
        Map<String, Object> map = new HashMap<>(10, 1.0f);
        //条件里面
        map.put("flow", listMap);
        //缓存所有的审批下条件，优化递归查询速度
        for (ExamineTypeEnum examineTypeEnum : ExamineTypeEnum.values()) {
            //关联业务流程和管理员审批
            if (examineTypeEnum.equals(ExamineTypeEnum.MANAGER) || examineTypeEnum.equals(ExamineTypeEnum.BIND_LABEL)) {
                continue;
            }
            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(examineTypeEnum.getServerName());
            examineTypeService.queryFlowListByBatchId(map, batchId);
        }
        List<ExamineFlowVO> examineFlowVOList = new ArrayList<>();
        List<UserInfo> data = adminService.queryUserInfoList().getData();
        for (ExamineFlow examineFlow : examineFlows) {
            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());
            ExamineFlowVO flowInfo = examineTypeService.createFlowInfo(examineFlow, map, data, ownerUserId);
            if (ObjectUtil.isEmpty(flowInfo)) {
                continue;
            }
            List<ExamineFlowAuthField> authFields = examineFlowAuthFieldService.lambdaQuery().eq(ExamineFlowAuthField::getFlowId, examineFlow.getFlowId()).list();
            List<ExamineFlowAuthField> authFieldList = authFields.stream().filter(e -> e.getParentId() == null).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(authFieldList)) {
                for (ExamineFlowAuthField authField : authFieldList) {
                    if (authField.getHasChildren() == 1) {
                        List<ExamineFlowAuthField> collect = authFields.stream().filter(e -> e.getParentId() != null).filter(e -> e.getParentId().equals(authField.getId())).collect(Collectors.toList());
                        authField.setFieldExtendList(collect);
                    }
                }
                List<ExamineFieldAuthBO> fieldAuthBOS = JSONUtil.toList(JSONUtil.parseArray(authFieldList), ExamineFieldAuthBO.class);
                flowInfo.setFieldAuthList(fieldAuthBOS);
            } else {
                flowInfo.setFieldAuthList(new ArrayList<>());
            }
            //添加语言包key
            Map<String, String> keyMap = new HashMap<>();
            String fieldName = examineFlow.getName();
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Id")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Id")).concat("Name");
            }
            if (StrUtil.isNotBlank(fieldName) && fieldName.endsWith("Ids")) {
                fieldName = fieldName.substring(0, fieldName.lastIndexOf("Ids")).concat("Names");
            }
            keyMap.put("name_resourceKey", "defaultParams." + "crmExamine" + examine.getLabel() + "." + fieldName);
            flowInfo.setLanguageKeyMap(keyMap);
            examineFlowVOList.add(flowInfo);
        }
        return examineFlowVOList;
    }


    @Override
    public BasePage<com.kakarote.core.feign.oa.entity.ExamineVO> queryOaExamineList(ExaminePageBO examinePageBo) {
        UserInfo user = UserUtil.getUser();
        if (examinePageBo.getCategoryId() != null) {
            Examine examine = getById(examinePageBo.getCategoryId());
            examinePageBo.setCategoryId(examine != null ? examine.getExamineInitId() : null);
        }
        examinePageBo.setLabel(0);
        BasePage<ExamineRecord> basePage = ((ExamineRecordLogMapper) examineRecordLogService.getBaseMapper()).selectRecordLogListByUser(examinePageBo.parse(), examinePageBo, user.getUserId(), user.getRoles());
        BasePage<com.kakarote.core.feign.oa.entity.ExamineVO> page = new BasePage<>(basePage.getCurrent(), basePage.getSize(), basePage.getTotal());
        List<com.kakarote.core.feign.oa.entity.ExamineVO> examineVoList = new ArrayList<>();
        for (ExamineRecord examineRecord : basePage.getList()) {
            Long typeId = examineRecord.getTypeId();
            if (typeId == null) {
                continue;
            }
            com.kakarote.core.feign.oa.entity.ExamineVO examineVO = oaService.getOaExamineById(typeId).getData();
            if(examineVO == null){
                continue;
            }
            examineVO.setCreateTime(examineRecord.getCreateTime());
            examineVoList.add(examineVO);
        }
        page.setList(examineVoList);
        return page;
    }


    @Override
    public BasePage<ExamineRecordInfoVO> queryCrmExamineList(ExaminePageBO examinePageBo) {
        BasePage<ExamineRecordInfoVO> page = new BasePage<>();
        return page;
    }

    @Override
    public List<Long> queryOaExamineIdList(Integer status, Long categoryId) {
        ExaminePageBO examinePageBo = new ExaminePageBO();
        UserInfo user = UserUtil.getUser();
        examinePageBo.setLabel(0);
        if (status != null && status < 0) {
            status = null;
        }
        examinePageBo.setStatus(status);
        examinePageBo.setCategoryId(categoryId);
        return ((ExamineRecordLogMapper) examineRecordLogService.getBaseMapper()).selectRecordTypeIdListByUser(examinePageBo, user.getUserId(), user.getRoles());
    }

    @Override
    public List<Long> queryCrmExamineIdList(Integer label, Integer status) {
        ExaminePageBO examinePageBo = new ExaminePageBO();
        UserInfo user = UserUtil.getUser();
        examinePageBo.setLabel(label);
        examinePageBo.setStatus(status);
        return ((ExamineRecordLogMapper) examineRecordLogService.getBaseMapper()).selectRecordTypeIdListByUser(examinePageBo, user.getUserId(), user.getRoles());
    }

    @Override
    public void batchAuditExamine(ExamineBO examineBO) {
        CrmBackLogBO crmBackLogBO = new CrmBackLogBO();
        crmBackLogBO.setPageType(0);
        crmBackLogBO.setType(1);
        IExamineRecordService examineRecordService = ApplicationContextHolder.getBean(IExamineRecordService.class);
        switch (examineBO.getType()) {
            case 4: //办公审批
              ExaminePageBO examinePageBo = new ExaminePageBO();
                Integer type = crmBackLogBO.getType();
                List<String> ids = new ArrayList<>();
                BeanUtil.copyProperties(crmBackLogBO, examinePageBo);
                examinePageBo.setStatus(type);
                examinePageBo.setTypeIdList(ids.stream().map(Long::valueOf).collect(Collectors.toList()));
                List<com.kakarote.core.feign.oa.entity.ExamineVO> checkOaList =queryOaExamineList(examinePageBo).getList();
                if (checkOaList.size() != 0) {
                    for (com.kakarote.core.feign.oa.entity.ExamineVO examineVO : checkOaList) {
                        if (ObjectUtil.isEmpty(examineVO.getExamineId()) || ObjectUtil.isEmpty(examineVO.getExamineRecordId())) {
                            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(0).getServerName());
                            // 修改审批
                            moduleService.updateCheckStatus(0, examineVO.getExamineId(), 1, null);
                            continue;
                        }
                        ExamineBO bo = new ExamineBO();
                        bo.setStatus(1);
                        bo.setTypeId(examineVO.getExamineId());
                        bo.setRecordId(examineVO.getExamineRecordId());
                        bo.setRemarks("批量通过");
                        examineRecordService.auditExamine(bo);
                    }
                }
                break;
            default:
                break;
        }
    }

    /**
     * 功能描述: <br>
     * 〈查询所有字段语言包key信息〉
     *
     * @param:
     * @return: java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @throws:
     * @author: zyh
     * @date: 2022/6/25 10:49
     */
    @Override
    public List<Map<String, Object>> getAllFieldLanguageRel() {
        List<Map<String, Object>> listMap = new ArrayList<>();

        List<Examine> examines = list();
        if (CollectionUtil.isNotEmpty(examines)) {
            for (Examine examine : examines) {
                //添加语言包key
                Map<String, Object> map = new HashMap<>();
                map.put("fileName", "defaultParams." + "crmExamine" + examine.getLabel() + "." + examine.getExamineName());
                map.put("chinese", examine.getExamineName());
                map.put("translateName", "");
                listMap.add(map);
            }
        }

        //审批流程
        List<ExamineFlowBO> examineFlowList = examineFlowService.queryAllFlowWithLabel();
        if (CollectionUtil.isNotEmpty(examineFlowList)) {
            for (ExamineFlowBO examineFlow : examineFlowList) {
                //添加语言包key
                Map<String, Object> map = new HashMap<>();
                map.put("fileName", "defaultParams." + "crmExamine" + examineFlow.getLabel() + "." + examineFlow.getName());
                map.put("chinese", examineFlow.getName());
                map.put("translateName", "");
                listMap.add(map);
                //添加语言包key
                Map<String, Object> remarksMap = new HashMap<>();
                map.put("fileName", "defaultParams." + "crmExamineRemarks" + examineFlow.getLabel() + "." + examineFlow.getRemarks());
                map.put("chinese", examineFlow.getRemarks());
                map.put("translateName", "");
                listMap.add(remarksMap);

            }
        }

        //错误信息
        for (ExamineCodeEnum codeEnum : ExamineCodeEnum.values()) {
            //添加语言包key
            Map<String, Object> map = new HashMap<>();
            map.put("fileName", "error." + codeEnum.getCode());
            map.put("chinese", AdminLanguageUtil.replaceMsg(codeEnum.getMsg()));
            map.put("translateName", "");
            listMap.add(map);
        }
        return listMap;
    }

    @Override
    public List<Examine> queryLabelStatusWithSort(Integer label, Integer status, Boolean isAdmin, Long userId, Long deptId, List<Long> ids) {
        return getBaseMapper().queryLabelStatusWithSort(label, status, isAdmin, userId, deptId, ids);
    }


    @Override
    public List<Map<String, Object>> queryExamineUserField(Integer label, Long examineId) {

        if (examineId == null) {
            Examine one = lambdaQuery().eq(Examine::getLabel, label).eq(Examine::getStatus, 1).one();
            if (ObjectUtil.isNotEmpty(one)) {
                examineId = one.getExamineId();
            } else {
                return new ArrayList<>();
            }
        }

        ExamineFlow flow = examineFlowService.lambdaQuery().eq(ExamineFlow::getExamineId, examineId).last("limit 1").one();

        if (flow != null) {
            List<ExamineFlow> examineFlows = examineFlowService.lambdaQuery().eq(ExamineFlow::getBatchId, flow.getBatchId()).list();

            List<Long> flowIds = examineFlows.stream().filter(e -> e.getExamineType().equals(ExamineTypeEnum.MEMBER_COMPONENT.getType())).map(ExamineFlow::getFlowId).collect(Collectors.toList());

            if (CollectionUtil.isNotEmpty(flowIds)) {
                List<Map<String, Object>> mapList = new ArrayList<>();

                List<ExamineFlowMemberComponent> list = examineFlowMemberComponentService.lambdaQuery().in(ExamineFlowMemberComponent::getFlowId, flowIds).list();

                list.forEach(e -> {
                    Map<String, Object> map = new HashMap<>();
                    String fieldName = e.getFieldName();
                    map.put("fieldName", fieldName);
                    mapList.add(map);
                });
                return mapList;
            }
        }

        return new ArrayList<>();
    }

    @Override
    public ExamineAdvancedConfigVO queryExamineAdvancedConfig(ExaminePreviewBO examinePreviewBO) {
        ExamineAdvancedConfigVO examineAdvancedConfigVO = new ExamineAdvancedConfigVO();
        Examine examine;
        Long recordId = examinePreviewBO.getRecordId();
        if (examinePreviewBO.getExamineId() == null) {
            if (recordId == null) {
                examine = lambdaQuery().eq(Examine::getLabel, examinePreviewBO.getLabel()).eq(Examine::getStatus, 1).one();
            } else {
                ExamineRecord record = examineRecordService.getById(recordId);
                Long examineId = Optional.ofNullable(record).orElse(new ExamineRecord()).getExamineId();
                examine = this.getById(examineId);

            }
        } else {
            //OA审批
            examine = this.getById(examinePreviewBO.getExamineId());
        }
        if (examine == null) {
            return examineAdvancedConfigVO;
        }
        //获取高级设置
        examineAdvancedConfigVO = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
        examineAdvancedConfigVO.setExamineId(examine.getExamineId());
        if (recordId != null) {
            ExamineFlowFinal flowFinal = examineFlowFinalService.lambdaQuery()
                    .eq(ExamineFlowFinal::getExamineId, examine.getExamineId())
                    .eq(ExamineFlowFinal::getRecordId, recordId)
                    .orderByDesc(ExamineFlowFinal::getSort, ExamineFlowFinal::getCreateTime)
                    .last("limit 1").one();

            if (ObjectUtil.isEmpty(flowFinal)) {
                List<ExamineFlowFinal> examineFlowFinalList = new ArrayList<>();
                List<ExamineFlow> examineFlows = examineFlowService.lambdaQuery().eq(ExamineFlow::getExamineId, examine.getExamineId()).orderByAsc(ExamineFlow::getSort).list();
                if (CollectionUtil.isNotEmpty(examineFlows)) {
                    for (ExamineFlow examineFlow : examineFlows) {
                        List<ExamineFlowOptional> flowOptionals = examineFlowOptionalService.lambdaQuery().eq(ExamineFlowOptional::getFlowId, examineFlow.getFlowId()).list();
                        ExamineFlowFinal examineFlowFinal = BeanUtil.copyProperties(examineFlow, ExamineFlowFinal.class);
                        examineFlowFinal.setRecordId(recordId);
                        if (CollectionUtil.isNotEmpty(flowOptionals)) {
                            examineFlowFinal.setType(CollectionUtil.getFirst(flowOptionals).getType());
                        }
                        examineFlowFinalList.add(examineFlowFinal);
                    }
                }

                if (CollectionUtil.isNotEmpty(examineFlowFinalList)) {
                    List<Long> collect = examineFlowFinalList.stream().map(ExamineFlowFinal::getFlowId).collect(Collectors.toList());

                    List<ExamineRecordLog> recordLogs = examineRecordLogService.lambdaQuery().in(ExamineRecordLog::getFlowId, collect).eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()).list();

                    if (CollectionUtil.isNotEmpty(recordLogs)) {
                        flowFinal = examineFlowFinalList.stream().filter(examineFlowFinal -> examineFlowFinal.getFlowId().equals(recordLogs.get(0).getFlowId())).findFirst().orElse(null);
                    } else {
                        // 获取examineFlowFinalList最后一个
                        flowFinal = examineFlowFinalList.get(examineFlowFinalList.size() - 1);
                    }
                }
            }

            if (flowFinal != null) {
                examineAdvancedConfigVO.setExamineFlowId(flowFinal.getFlowId());
            }


        }
        return examineAdvancedConfigVO;
    }


    @Override
    public List<ExamineFlowVO> getPreviewExamineFlows(ExaminePreviewBO examinePreviewBO) {
        Examine examine;
        Long recordId = examinePreviewBO.getRecordId();
        if (examinePreviewBO.getExamineId() == null) {
            if (recordId == null) {
                examine = lambdaQuery().eq(Examine::getLabel, examinePreviewBO.getLabel()).eq(Examine::getStatus, 1).one();
            } else {
                ExamineRecord record = examineRecordService.getById(recordId);
                Long examineId = Optional.ofNullable(record).orElse(new ExamineRecord()).getExamineId();
                examine = this.getById(examineId);
            }
        } else {
            //OA审批
            examine = this.getById(examinePreviewBO.getExamineId());
        }
        if (examine == null) {
            return new ArrayList<>();
        }

        List<ExamineFlowVO> examineFlowVOList = getExamineFlowVOList(examine, examinePreviewBO.getOwnerUserId());
        Map<String, Object> dataMap = examinePreviewBO.getDataMap();
        if (dataMap == null) {
            ExamineRecord examineRecord = examineRecordService.getById(examinePreviewBO.getRecordId());
            dataMap = new HashMap<>(8);
            List<ExamineFlowConditionDataVO> conditionDataVoS = this.previewFiledName(examineRecord.getLabel(), null, examineRecord.getExamineId());
            //判断有无条件审核，如果有获取相应数据
            if (conditionDataVoS != null) {
                List<String> fieldList = conditionDataVoS.stream().map(ExamineFlowConditionDataVO::getFieldName).collect(Collectors.toList());
                fieldList.removeIf(StrUtil::isEmpty);
                if (CollUtil.isNotEmpty(fieldList)) {
                    ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
                    dataMap = moduleService.getConditionMap(examineRecord.getLabel(), examineRecord.getTypeId(), examineRecord.getRecordId());
                } else {
                    dataMap.put(ExamineConst.CREATE_USER_ID, examineRecord.getCreateUserId());
                }
            }
        }

        List<ExamineFlowVO> examineFlowVoS = new ArrayList<>();
        this.getAllConformExamineFlow(examineFlowVOList, dataMap, examineFlowVoS);

        //非初始审批 - 新建数据之后预览流程时补充自选用户信息
        this.supplementOptionalUserInfo(examineFlowVoS, examinePreviewBO.getRecordId(), examine.getExamineId());

        List<Long> list = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getRecordId, recordId).list().stream().filter(Objects::nonNull).map(ExamineFlowFinal::getFlowId).collect(Collectors.toList());
        examineFlowVoS.removeIf(examineFlowVO -> list.contains(examineFlowVO.getFlowId()));
        return examineFlowVoS;
    }

    /**
     * 获取某个公司的唯一业务流程
     */
    @Override
    public ExamineInfoVo getBizExamine(Integer label,Long deptId){
        Examine examine = baseMapper.getUniqueBizExamine(deptId, label);
        ExamineInfoVo examineInfoVo = new ExamineInfoVo();
        BeanUtil.copyProperties(examine, examineInfoVo);
        return examineInfoVo;
    }

    private List<Long> getSameLevelDeptId(Long deptId){
        Result<List<Long>> listResult = adminService.querySameLevelDeptId(deptId);
        if(listResult.hasSuccess()){
            return listResult.getData();
        }
        return new ArrayList<>();
    }

}
